#include "StdAfx.h"
#include "CodeFile.h"
#include "CharacterOperations.h"

using std::runtime_error;		using std::ifstream;
using std::string;

const int NumberOfLetters = 27;
const int IntegerForZero = 48;

// Initialises a stream from the provided filepath
CodeFile::CodeFile(std::string filePath)
{
	// Set up the file stream
	_fileStream = ifstream(filePath, ifstream::in);

	// Make sure whitespace is parsed
	_fileStream >> std::noskipws;

	if(!_fileStream.is_open())
	{
		throw runtime_error("the path " + filePath + " could not be opened");	
	}
}

// Closes the stream
CodeFile::~CodeFile(void)
{
	// We are finished with the stream so close it
	_fileStream.close();
}

// Pulls the next char from the stream into Lookahead
void CodeFile::GetNextChar()
{
	// Pull a single character from the stream
	_fileStream >> Lookahead;

	if(_fileStream.eof())
	{
		Lookahead = 0;
	}
}

// Skips whitespace
void CodeFile::SkipWhite()
{
	while(IsWhite(Lookahead))
	{
		GetNextChar();
	}
}

// Matches a single character and progresses the stream
void CodeFile::Match(char m)
{
	if(Lookahead == m)
	{
		GetNextChar();
		SkipWhite();
	}
	else
	{
		throw runtime_error("expected the next char for Match(char) to be " + m);
	}
}

// Pulls a number from the stream
int CodeFile::GetNum()
{
	if(!IsNum(Lookahead))
	{
		throw runtime_error("expected a number inside GetNum()");
	}

	int number = 0;

	while(IsNum(Lookahead))
	{
		number *= 10;
		number += (int)Lookahead - IntegerForZero;
		GetNextChar();
	}

	SkipWhite();
	
	return number;
}

// Pulls a name from the stream
char CodeFile::GetName()
{
	if(!IsLetter(Lookahead))
	{
		throw runtime_error("expected a letter inside GetName()");		
	}
	
	char name;

	if(IsLetter(Lookahead))
	{
		name = Lookahead;
		GetNextChar();
	}

	SkipWhite();

	return name;
}